package com.easygem.common.utils;

import com.easygem.common.model.front.ResourceInfo;
import com.easygem.common.vo.front.ResourceInfoVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 罗力
 * @version 1.0
 * @className ExcelUtils
 * @description TODO 某某类
 * @date 2024/12/29 19:01
 */

public class ExcelUtils<T> {

    /**
     * 去重方法
     */
    public static List<ResourceInfoVO> deWeight(List<ResourceInfoVO> list) {
        // 使用 HashSet 来存储已经出现过的电话号码
        Set<String> seenPhones = new HashSet<>();
        List<ResourceInfoVO> uniqueOjb = new ArrayList<>();
        for (ResourceInfoVO obj : list) {
            if (seenPhones.add(obj.getPhoneA())) {  // add() 返回true表示该电话未出现过
                uniqueOjb.add(obj);
            }
        }
        return uniqueOjb;
    }
    /**
     * 资源实体类去重方法
     */
    public static List<ResourceInfo> deWeightResourceInfo(List<ResourceInfo> list) {
        Set<String> seenPhones = new HashSet<>();
        List<ResourceInfo> uniqueList = new ArrayList<>();
        for (ResourceInfo obj : list) {
            String phoneA = obj.getPhoneA();
            String phoneB = obj.getPhoneB();
            boolean isDuplicate = false;
            // 检查 phoneA 是否重复
            if (phoneA != null) {
                if (!seenPhones.add(phoneA)) {
                    isDuplicate = true;
                }
            }
            // 检查 phoneB 是否重复
            if (phoneB != null) {
                if (!seenPhones.add(phoneB)) {
                    isDuplicate = true;
                }
            }
            // 如果 phoneA 和 phoneB 都不重复，添加到结果列表
            if (!isDuplicate) {
                uniqueList.add(obj);
            }
        }
        return uniqueList;
    }
    /**
     * 将excel文件数据转换为集合
     *
     * @param file      excel文件
     * @param clazz     转换后的集合中的对象类型
     * @param headerMap 表头对应的字段map集合 格式：键：excel表头名 值：字段名
     * @param <T>       泛型
     * @return 转换后的集合
     * @throws Exception 异常
     */
    public static <T> List<T> parseExcel(MultipartFile file, Class<T> clazz, Map<String, String> headerMap) throws Exception {
        List<T> resultList = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream()) {
            Workbook workbook;
            if (file.getOriginalFilename().endsWith(".xlsx")) {
                workbook = new XSSFWorkbook(inputStream); // .xlsx 文件
            } else {
                workbook = WorkbookFactory.create(inputStream); // .xls 文件
            }
            Sheet sheet = workbook.getSheetAt(0);
            Iterator<Row> rowIterator = sheet.iterator();

            if (!rowIterator.hasNext()) {
                throw new IllegalArgumentException("The Excel file is empty");
            }

            // 获取表头行（假设第一行是表头）
            Row headerRow = rowIterator.next();

            // 迭代数据行
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                T object = clazz.getDeclaredConstructor().newInstance();  // 创建对象

                // 遍历每列，并通过映射表头找到对应字段
                for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) {
                    Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    String header = headerRow.getCell(i).getStringCellValue().trim(); // 获取表头中文名
                    String fieldName = headerMap.get(header);  // 获取对应的字段名

                    if (fieldName != null) {
                        // 使用反射设置字段值
                        Field field = clazz.getDeclaredField(fieldName);
                        field.setAccessible(true);

                        // 根据单元格类型设置字段值
                        Object value = getCellValue(cell, field.getType());
                        if (value != null) {
                            field.set(object, value);
                        }
                    }
                }
                resultList.add(object);  // 将解析的对象添加到结果列表
            }
        } catch (IOException e) {
            throw new RuntimeException("Failed to process Excel file", e);
        }
        return resultList;
    }


    private static Object getCellValue(Cell cell, Class<?> fieldType) {
        try {
            CellType cellType = cell.getCellTypeEnum();

            // 1. 处理字符串单元格
            if (cellType == CellType.STRING) {
                String value = cell.getStringCellValue().trim();
                return convertStringToTargetType(value, fieldType);
            }

            // 2. 处理数值单元格
            if (cellType == CellType.NUMERIC) {
                double numericValue = cell.getNumericCellValue();

                // 如果是日期格式，优先返回Date类型
//                if (DateUtil.isCellDateFormatted(cell)) {
//                    Date dateValue = cell.getDateCellValue();
//                    return convertDateToTargetType(dateValue, fieldType);
//                }

                // 根据目标字段类型转换数值
                return convertNumericToTargetType(numericValue, fieldType);
            }

            // 3. 处理布尔值单元格
            if (cellType == CellType.BOOLEAN) {
                boolean boolValue = cell.getBooleanCellValue();
                return convertBooleanToTargetType(boolValue, fieldType);
            }

            // 4. 处理公式单元格
            if (cellType == CellType.FORMULA) {
                return handleFormulaCell(cell, fieldType);
            }

            // 5. 空白单元格或其他类型返回null
            return null;

        } catch (Exception e) {
            // 记录转换失败的错误信息
            System.err.println("单元格类型转换失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 将字符串转换为目标字段类型
     */
    private static Object convertStringToTargetType(String value, Class<?> targetType) {
        if (value.isEmpty()) return null;

        try {
            if (targetType == String.class) {
                return value;
            } else if (targetType == Integer.class || targetType == int.class) {
                return Integer.parseInt(value);
            } else if (targetType == Double.class || targetType == double.class) {
                return Double.parseDouble(value);
            } else if (targetType == Long.class || targetType == long.class) {
                return Long.parseLong(value);
            } else if (targetType == Boolean.class || targetType == boolean.class) {
                // 支持 "true"/"false" 或 "是"/"否" 等常见布尔值
                return parseBoolean(value);
            } else if (targetType == Date.class) {
                // 尝试解析字符串为日期（需定义日期格式）
                return parseDate(value);
            } else {
                return null; // 不支持的类型
            }
        } catch (NumberFormatException e) {
            System.err.println("字符串转数值失败: " + value);
            return null;
        }
    }

    /**
     * 将数值转换为目标字段类型
     */
    private static Object convertNumericToTargetType(double numericValue, Class<?> targetType) {
        if (targetType == Integer.class || targetType == int.class) {
            return (int) numericValue;
        } else if (targetType == Double.class || targetType == double.class) {
            return numericValue;
        } else if (targetType == Long.class || targetType == long.class) {
            return (long) numericValue;
        } else if (targetType == String.class) {
            // 数值转字符串（避免科学计数法）
            return String.valueOf((long) numericValue); // 如果是整数
            // 或 DecimalFormat.format(numericValue); // 需要自定义格式
        } else if (targetType == Boolean.class || targetType == boolean.class) {
            return numericValue != 0; // 0 为 false，非0为 true
        } else if (targetType == Date.class) {
            // 将数值解释为Excel日期（需处理1900日期系统）
            return DateUtil.getJavaDate(numericValue);
        } else {
            return null; // 不支持的类型
        }
    }

    /**
     * 处理公式单元格
     */
    private static Object handleFormulaCell(Cell cell, Class<?> targetType) {
        try {
            // 尝试获取公式计算结果
            switch (cell.getCachedFormulaResultTypeEnum()) {
                case NUMERIC:
                    return convertNumericToTargetType(cell.getNumericCellValue(), targetType);
                case STRING:
                    return convertStringToTargetType(cell.getStringCellValue(), targetType);
                case BOOLEAN:
                    return convertBooleanToTargetType(cell.getBooleanCellValue(), targetType);
                default:
                    return null;
            }
        } catch (Exception e) {
            System.err.println("公式解析失败: " + e.getMessage());
            return null;
        }
    }

    /**
     * 布尔值转换（支持自定义逻辑）
     */
    private static Object convertBooleanToTargetType(boolean boolValue, Class<?> targetType) {
        if (targetType == Boolean.class || targetType == boolean.class) {
            return boolValue;
        } else if (targetType == String.class) {
            return boolValue ? "是" : "否"; // 自定义字符串表示
        } else if (targetType == Integer.class || targetType == int.class) {
            return boolValue ? 1 : 0; // 用1/0表示布尔值
        } else {
            return null;
        }
    }

    /**
     * 解析字符串为布尔值（支持更多格式）
     */
    private static Boolean parseBoolean(String value) {
        if (value.equalsIgnoreCase("true") || value.equals("是") || value.equals("1")) {
            return true;
        } else if (value.equalsIgnoreCase("false") || value.equals("否") || value.equals("0")) {
            return false;
        } else {
            throw new IllegalArgumentException("无效的布尔值: " + value);
        }
    }

    /**
     * 解析字符串为日期（需自定义格式）
     */
    private static Date parseDate(String value) {
        SimpleDateFormat[] dateFormats = {
                new SimpleDateFormat("yyyy-MM-dd"),
                new SimpleDateFormat("yyyy/MM/dd"),
                new SimpleDateFormat("dd-MM-yyyy")
        };
        for (SimpleDateFormat format : dateFormats) {
            try {
                return format.parse(value);
            } catch (ParseException ignored) {
            }
        }
        throw new IllegalArgumentException("无法解析日期: " + value);
    }

    /**
     * 批量处理接口
     */
    public interface BatchProcessor<T> {
        void processBatch(List<T> batch, boolean isLastBatch) throws Exception;
    }

    /**
     * 计算Excel文件中的行数
     *
     * @param file Excel文件
     * @return 总行数（不包括表头）
     * @throws IOException IO异常
     * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException 格式异常
     */
    public static int countRows(java.io.File file) throws IOException, org.apache.poi.openxml4j.exceptions.InvalidFormatException {
        try (InputStream is = new java.io.FileInputStream(file);
             Workbook workbook = WorkbookFactory.create(is)) {
            Sheet sheet = workbook.getSheetAt(0);
            return sheet.getPhysicalNumberOfRows() - 1; // 减去表头行
        }
    }

    /**
     * 分批处理Excel文件数据
     *
     * @param file Excel文件
     * @param clazz 目标类
     * @param headerMap 表头映射
     * @param processor 批处理器
     * @param batchSize 批大小
     * @param <T> 目标类泛型
     * @throws Exception 处理异常
     * @throws org.apache.poi.openxml4j.exceptions.InvalidFormatException 格式异常
     */
    public static <T> void processExcelInBatches(java.io.File file, Class<T> clazz, 
                                                Map<String, String> headerMap,
                                                BatchProcessor<T> processor, 
                                                int batchSize) throws Exception, org.apache.poi.openxml4j.exceptions.InvalidFormatException {
        try (InputStream is = new java.io.FileInputStream(file);
             Workbook workbook = WorkbookFactory.create(is)) {
            
            Sheet sheet = workbook.getSheetAt(0);
            Iterator<Row> rowIterator = sheet.iterator();
            
            if (!rowIterator.hasNext()) {
                throw new IllegalArgumentException("The Excel file is empty");
            }
            
            // 获取表头行
            Row headerRow = rowIterator.next();
            
            // 创建表头映射
            Map<Integer, String> columnToFieldMap = new HashMap<>();
            for (int i = 0; i < headerRow.getPhysicalNumberOfCells(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) {
                    String header = cell.getStringCellValue().trim();
                    String fieldName = headerMap.get(header);
                    if (fieldName != null) {
                        columnToFieldMap.put(i, fieldName);
                    }
                }
            }
            
            List<T> batch = new ArrayList<>(batchSize);
            
            // 处理数据行
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                T object = clazz.getDeclaredConstructor().newInstance();
                
                // 处理每一列
                for (Map.Entry<Integer, String> entry : columnToFieldMap.entrySet()) {
                    int columnIndex = entry.getKey();
                    String fieldName = entry.getValue();
                    
                    Cell cell = row.getCell(columnIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    Field field = clazz.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    
                    Object value = getCellValue(cell, field.getType());
                    if (value != null) {
                        field.set(object, value);
                    }
                }
                
                batch.add(object);
                
                // 如果达到批处理大小或者是最后一行，则处理这一批
                if (batch.size() >= batchSize || !rowIterator.hasNext()) {
                    processor.processBatch(batch, !rowIterator.hasNext());
                    batch = new ArrayList<>(batchSize);
                }
            }
        }
    }
}
